package cn.jinjimi.app.main.activity;

import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.support.v4.content.ContextCompat;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebView;

import com.qiyukf.unicorn.api.ConsultSource;
import com.qiyukf.unicorn.api.Unicorn;
import com.tencent.bugly.crashreport.CrashReport;

import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.json.JSONObject;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;

import bolts.Continuation;
import bolts.Task;
import cn.jinjimi.app.AccountManager;
import cn.jinjimi.app.R;
import cn.jinjimi.app.ShareProxy;
import cn.jinjimi.app.bean.BundleKey;
import cn.jinjimi.app.bean.Constants;
import cn.jinjimi.app.bean.QuesCode;
import cn.jinjimi.app.bean.RouterConstants;
import cn.jinjimi.app.bean.RouterService;
import cn.jinjimi.app.bean.WXPayResult;
import cn.jinjimi.app.controller.FileController;
import cn.jinjimi.app.controller.event.DataEvent;
import cn.jinjimi.app.controller.event.LoginSuccessEvent;
import cn.jinjimi.app.controller.event.PayReturnEvent;
import cn.jinjimi.app.controller.event.WebEvent;
import cn.jinjimi.app.custom.entity.Custom;
import cn.jinjimi.app.main.dialog.ShareDialog;
import cn.jinjimi.app.main.extend.ToolBarWebActivity;
import cn.jinjimi.app.main.widget.MyProgress;
import cn.jinjimi.app.main.widget.MyWebView;
import cn.jinjimi.app.main.widget.ToolBar.WebToolbar;
import cn.jinjimi.app.managers.NetRouteParamManager;
import cn.jinjimi.app.util.PhotoUtils;
import cn.jinjimi.app.webview.AbstractJavascriptBridge;
import cn.jinjimi.app.webview.WebViewHelper;
import cn.jinjimi.app.webview.WebViewJavascriptBridge;
import cn.jinjimi.app.webview.event.ReqLoginEvent;
import cn.jinjimi.app.webview.event.ReqLogoutEvent;
import cn.jinjimi.app.webview.event.ReqRouteUrlEvent;
import cn.jinjimi.app.webview.event.ReqSetTitleEvent;
import cn.jinjimi.app.webview.event.ReqUploadPhotoEvent;
import cn.jinjimi.app.webview.event.Route2CustomerService;
import cn.jinjimi.app.webview.utils.WebUtils;
import cn.jinjimi.base.util.LogUtil;
import cn.jinjimi.base.util.SharePlatForm;
import cn.jinjimi.base.util.StringUtils;
import cn.jinjimi.base.util.ToastUtils;
import cn.jinjimi.base.util.URLUtil;
import cn.jinjimi.domain.data.net.API;
import cn.jinjimi.domain.data.net.PageService;
import cn.jinjimi.domain.entity.UploadedFile;
import cn.jinjimi.framework.pay.WXPayTask;
import cn.jinjimi.framework.router.Router;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Response;

import static cn.jinjimi.app.plugin.WebPlugin.PluginParam;


/**
 *
 * @author zhenhua
 */
public class WebActivity extends ToolBarWebActivity {
    private static final String TAG = WebActivity.class.getSimpleName();

    private MyWebView webView;
    private MyProgress progressBar;
    private Map<String, String> mHttpHeaders;

    private String mCurrentURL = null;
    private String mCurrentTitle = null;
    private List<String> titles = new ArrayList<>();
    public ValueCallback<Uri> mUploadMessage;
    private WebViewJavascriptBridge handler;
    private String mLastUrl;
    private AbstractJavascriptBridge.BaseAction mCurrentAction;

    public static void launch(Context startActivity, int type, String url, String title) {
        if (startActivity == null) {
            return;
        }
        Intent intent = new Intent(startActivity, WebActivity.class);
        intent.putExtra(BundleKey.TYPE, type);
        intent.putExtra(BundleKey.URL, url);
        intent.putExtra(BundleKey.TITLE, title);
        launch(startActivity, intent);
    }

    public static void launch(Context startActivity, String url, Custom custom) {
        if (startActivity == null) {
            return;
        }
        Intent intent = new Intent(startActivity, WebActivity.class);
        intent.putExtra(BundleKey.URL, url);
        launch(startActivity, intent);
    }

    public static void launch(Context startActivity, Intent intent) {
        for (Map.Entry<String, String> entry : NetRouteParamManager.getInstance().getRouterParam().entrySet()) {
            intent.putExtra(entry.getKey(), entry.getValue());
        }
        startActivity.startActivity(intent);
    }

    @Override
    protected void beforeInitView() {
        setContentView(R.layout.activity_web);
        getTitleBar().getmBackIv().setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onBack();
            }
        });
        getTitleBar().getmCloseIv().setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onBackPressed();
            }
        });
        getIntentData(getIntent());
    }

    @Override
    protected void initial() {
        initView();
        initData();
    }

    /**
     * 当用户回退时
     */
    private void onBack() {
        if (webViewIsPermit() && webView.canGoBack()) {
            goBackAndHandleTitle();
        } else {
            onBackPressed();
        }
    }

    private void getIntentData(Intent intent) {
        // bad code
        final String url = intent.getStringExtra(PluginParam.PLUGIN_URL);
        if (!TextUtils.isEmpty(url) && url.startsWith("jinjimiapp:/")) {
            Task.callInBackground(new Callable<String>() {
                @Override
                public String call() throws Exception {
                    Uri uri = Uri.parse(url);
                    Response<ResponseBody> res = API.create(PageService.class)
                        .getDirectUrl(Constants.Env.API_BASE_URL + "page/router/" + uri.getPath() + "?" + uri.getQuery()).execute();
                    if (res != null && res.isSuccessful()) {
                        JSONObject result = new JSONObject(res.body().string());
                        if (result.has("result")) {
                            return result.getString("result");
                        }
                    }
                    return null;
                }
            }).continueWith(new Continuation<String, Void>() {
                @Override
                public Void then(Task<String> task) throws Exception {
                    String realUrl = task.getResult();
                    if (!TextUtils.isEmpty(realUrl)) {
                        mCurrentURL = realUrl;
                        loadUrl(mCurrentURL);
                    }
                    return null;
                }
            }, Task.UI_THREAD_EXECUTOR);
        } else {
            mCurrentURL = url;
        }

        //兼容direct
        if (TextUtils.isEmpty(mCurrentURL) && intent.hasExtra(RouterService.ROUTER_WEB_ROUTER_DIRECT)) {
            mCurrentURL = intent.getStringExtra(RouterService.ROUTER_WEB_ROUTER_DIRECT);
        }
        mCurrentTitle = intent.getStringExtra(PluginParam.PLUGIN_TITLE);
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
        getIntentData(intent);
        initData();
    }

    protected void initView() {
        webView = (MyWebView) findViewById(R.id.wv_webView);
        progressBar = (MyProgress) findViewById(R.id.progress);
        progressBar.setBackgroundColor(ContextCompat.getColor(WebActivity.this, R.color.white));
        progressBar.setProgressColor(ContextCompat.getColor(WebActivity.this, R.color.orange));
        setUpWebView();

        /* 初始化Javascript接口 */
        handler = new WebViewJavascriptBridge(webView);
        setSwipeEnabled(false);
    }

    protected void initData() {
        if (mCurrentURL == null) {
            return;
        }

        if (StringUtils.isNotEmpty(mCurrentTitle)) {
            setTitle(mCurrentTitle);
            titles.add(mCurrentTitle);
        }

        loadUrl(mCurrentURL);
        CrashReport.setJavascriptMonitor(webView, false);
    }

    private Map<String, String> getHttpHeaders() {
        if (mHttpHeaders == null) {
            mHttpHeaders = new HashMap<>();
        }
        return mHttpHeaders;
    }

    /**
     * 加载触屏版页面
     *
     * @param url
     */
    private void loadUrl(String url) {
        LogUtil.d(TAG, url);
        if (WebUtils.isDoubleClick()) {
            return;
        }

        boolean isDomain = WebUtils.isDomain(url);
        //预处理要加载的URL
        if (isDomain) {
            handler.enableJavascriptInterface(true);
            String token = AccountManager.getInstance().getToken();
            if (webViewIsPermit()) {
                webView.loadUrl(URLUtil.appendParam(url, Constants.ParamKey.APP_TOKEN, token), getHttpHeaders());
            }
        }
    }

    public void doOutUrlShare() {
        if (webViewIsPermit()) {
            ShareDialog shareDialog = new ShareDialog.Builder()
                    .SharePlatForm(SharePlatForm.getDefaultPlatform())
                    .ShareUrl(webView.getUrl())
                    .Title(webView.getTitle())
                    .ShareType(ShareProxy.ShareType.COMMON)
                    .build(WebActivity.this);
            shareDialog.show();
        }
    }

    private void setUpWebView() {
        WebChromeClient webChromeClient = new WebChromeClient() {
            // For Android 3.0-
            public void openFileChooser(ValueCallback<Uri> uploadMsg) {
                mUploadMessage = uploadMsg;
                Intent i = new Intent(Intent.ACTION_GET_CONTENT);
                i.addCategory(Intent.CATEGORY_OPENABLE);
                i.setType("image/*");
                startActivityForResult(Intent.createChooser(i, "File Chooser"), QuesCode.QuesFileChooserCode);

            }

            // For Android 3.0+
            public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
                mUploadMessage = uploadMsg;
                Intent i = new Intent(Intent.ACTION_GET_CONTENT);
                i.addCategory(Intent.CATEGORY_OPENABLE);
                i.setType("*/*");
                startActivityForResult(Intent.createChooser(i, "File Browser"), QuesCode.QuesFileChooserCode);
            }

            //For Android 4.1
            public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
                mUploadMessage = uploadMsg;
                Intent i = new Intent(Intent.ACTION_GET_CONTENT);
                i.addCategory(Intent.CATEGORY_OPENABLE);
                i.setType("image/*");
                startActivityForResult(Intent.createChooser(i, "File Chooser"), QuesCode.QuesFileChooserCode);
            }

            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                super.onProgressChanged(view, newProgress);
                progressBar.setVisibility(View.VISIBLE);
                progressBar.setProgress(newProgress);
                if (newProgress == Constants.PROGRESS_MAX) {
                    progressBar.setProgress(0);
                    progressBar.setVisibility(View.GONE);
                }
            }

            @Override
            public void onReceivedTitle(WebView view, String title) {
                super.onReceivedTitle(view, title);
                //当前页没有标题
                if (null == mCurrentTitle) {
                    setTitle(title);
                    titles.add(title);
                }
            }
        };

        webView.setWebChromeClient(webChromeClient);
        WebViewHelper.setUpWebView(this, webView);
    }

    /**
     * 浏览器返回上一页并设置标题
     */
    private void goBackAndHandleTitle() {
        webView.goBack();

        getTitleBar().setmCloseIv(true, "");

        if (titles.size() == 1) {
            setTitle(titles.get(0));
        } else if (titles.size() > 1) {
            titles.remove(titles.size() - 1);
            setTitle(titles.get(titles.size() - 1));
        }
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && webViewIsPermit() && webView.canGoBack()) {
            goBackAndHandleTitle();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    /**
     * 显示分享按钮
     */
    public void showShareButton() {
        showShareButton(null);
    }

    /**
     * 显示分享按钮
     */
    public void showShareButton(final View.OnClickListener listener) {
        WebToolbar.ToolbarActionImage action = new WebToolbar.ToolbarActionImage("share");
        //only one share button one time.
        if (getTitleBar().getActionButtonByTag(action) == null) {
            action.icon = ContextCompat.getDrawable(this, R.drawable.nav_icon_share);
            getTitleBar().putActionButton(action, new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    handler.callJSHandler("onShareButtonClicked", null);
                    if (listener != null) {
                        listener.onClick(v);
                    }
                }
            });
        }
    }

    /**
     * 隐藏分享按钮
     */
    public void hideShareButton() {
        WebToolbar.ToolbarActionImage action = new WebToolbar.ToolbarActionImage("share");
        getTitleBar().removeActionButton(action);
    }


    /**
     * 处理webview的跳转
     *
     * @param directUrl
     */
    private void dealWebViewSkip(String directUrl) {
        if (directUrl.startsWith("javascript:")) {
            if (webViewIsPermit()) {
                webView.loadUrl(directUrl);
            }
        } else {
            //每次页面跳转原生端默认清楚右上角的menu;
            removeAllMenu();
            Router.create(WebActivity.this, directUrl).open();
        }
    }

    /**
     * 删除右侧所有菜单栏
     */
    public void removeAllMenu() {
        getTitleBar().removeAllActionButtons();
    }


    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onWebEvent(WebEvent event) {
        if (isFinishing() || !webViewIsPermit()) {
            return;
        }

        switch (event.state) {
            case DataEvent.HEADER:
                if ("200 OK".equals(event.headers.get("Status"))) {
                    webView.loadUrl(event.loadUrl, event.outHeader);
                } else {
                    webView.loadUrl("file:///android_asset/404.html");
                }
                break;
            default:break;
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onPayReturnEvent(PayReturnEvent event) {
        if (event != null) {
            if (event.payOrder != null && event.payOrder.type == WXPayTask.TYPE) {
                String returnUrl = event.payOrder.return_url;
                ToastUtils.toastMessage(this, event.message);
                if (StringUtils.isNotEmpty(returnUrl) && webViewIsPermit()) {
                    webView.loadUrl(returnUrl.trim());
                }
            }
        }
    }


    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onLoginSuccessEvent(LoginSuccessEvent event) {
        if (AccountManager.getInstance().isLogin() && webViewIsPermit()) {
            webView.loadUrl("javascript:onLoginSuccess('" + AccountManager.getInstance().getAccount().token + "')");
        }

        loadUrl(mCurrentURL);
    }


    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onJSGoLoginEvent(ReqLoginEvent event) {
        if (AccountManager.getInstance().isLogin() && webViewIsPermit()) {
            webView.loadUrl("javascript:onLoginSuccess('" + AccountManager.getInstance().getAccount().token + "')");
            return;
        }

        if (webViewIsPermit()) {
            LoginActivity.setLoginFrom(webView.getUrl());
            Intent intent = new Intent(WebActivity.this, LoginActivity.class);
            startActivity(intent);
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onLogoutEvent(ReqLogoutEvent event) {
        if (AccountManager.getInstance().isLogin()) {
            AccountManager.getInstance().logout();
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onRoute2CustomerServiceEvent(Route2CustomerService event) {
        String title = "在线客服";
        /**
         * 设置访客来源，标识访客是从哪个页面发起咨询的，用于客服了解用户是从什么页面进入。
         * 三个参数分别为：来源页面的url，来源页面标题，来源页面额外信息（保留字段，暂时无用）。
         * 设置来源后，在客服会话界面的"用户资料"栏的页面项，可以看到这里设置的值。
         */
        ConsultSource source = new ConsultSource(mCurrentURL, title, "custom information string");
        /**
         * 请注意： 调用该接口前，应先检查Unicorn.isServiceAvailable()，
         * 如果返回为false，该接口不会有任何动作
         *
         * @param context 上下文
         * @param title   聊天窗口的标题
         * @param source  咨询的发起来源，包括发起咨询的url，title，描述信息等
         */
        Unicorn.openServiceActivity(this, title, source);
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onReqRouteUrl(ReqRouteUrlEvent event) {
        if (webViewIsPermit()) {
            loadUrl(event.url);
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onReqUploadPhoto(ReqUploadPhotoEvent event) {
        mCurrentAction = event.action;
        PhotoUtils.pickPhoto(this, false);
    }

    /**
     * 微信支付
     */

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onEvent(WXPayResult result) {
        handler.callJSHandler("JJMJSBOX.wxpayComplete", result.errCode);
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onHandleSetTitleEvent(ReqSetTitleEvent event) {
        setTitle(event.title);
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        String path = PhotoUtils.handlePhotoResult(this, intent, requestCode, resultCode);
        if (!TextUtils.isEmpty(path)) {
            File file = new File(path);
            if (file.exists()) {
                Map<String, File> files = new HashMap<>();
                files.put("file", file);

                FileController.uploadFile(files)
                        .onSuccess(new Continuation<List<UploadedFile>, Void>() {
                            @Override
                            public Void then(Task<List<UploadedFile>> task) throws Exception {
                                if (task.isCompleted()) {
                                    List<UploadedFile> uploadedFiles = task.getResult();
                                    if (uploadedFiles != null && uploadedFiles.size() >0) {
                                        if (mCurrentAction != null) {
                                            for (UploadedFile f : uploadedFiles) {
                                                JSONObject obj = new JSONObject();
                                                obj.put("callbackId", mCurrentAction.callbackId);
                                                obj.put("photoUrl", f.filePath);
                                                handler.callJSHandler(mCurrentAction.callbackFunction, obj.toString());
                                            }
                                        }
                                    }
                                }
                                return null;
                            }
                        });
            }
        }
    }

    private boolean firstFlag;

    @Override
    protected void onResume() {
        super.onResume();
        if (webViewIsPermit() && firstFlag) {
            WebViewJavascriptBridge.onRefreshWebView(webView);
            webView.onResume();
        } else {
            firstFlag = true;
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (webViewIsPermit()) {
            webView.onPause();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        NetRouteParamManager.getInstance().clearRouterParam();
        if (webViewIsPermit()) {
            ViewGroup parent = ((ViewGroup) webView.getParent());
            if (parent != null) {
                parent.removeView(webView);
            }

            webView.removeJavascriptInterface(WebViewJavascriptBridge.JS_BRIDGE_NAME);
            webView.removeAllViews();
            webView.clearHistory();
            webView.destroy();
        }
    }


    private boolean webViewIsPermit() {
        return webView != null && !webView.isDestory();
    }
}